#include "StdAfx.h"
#include "UnderSea_Monitor.h"
#include "Can1.h"
#include ".\include\Can\AdvCan.h"
#include ".\include\Can\AdvCANIO.h"
#include ".\include\Can\CanBus2.0.h"
#include "Common.h"

#define TIMEGAP 10
Can1::Can1(void)
{

	m_bOpened = FALSE;
	m_wProtocolType = CANBUS_PROTOCOL_20A;
	m_nBTR0 = 0x03;                                 // Baud rate is 125kps
	m_nBTR1 = 0x1c;
	m_nAcpCode = 0;
	m_nAcpMask = 255;
	m_nIntMask = 0;
	m_nOutCtrlCode = 250;
	m_nDevNum = 4;
	m_bGFFlag = FALSE;
}

Can1::~Can1(void)
{
}


#define TOTAL_COUNT 10000                          // Message count
bool g_bAppEnd = false;


BOOL Can1::OpenCan1(CWnd *pWnd)
{

	CString strdevnum = CCommon::GetIniString("CAN","DevNum",strFileName);
	CString strscantime = CCommon::GetIniString("CAN","scantime",strFileName);
	CString strtimeout = CCommon::GetIniString("CAN","Timeout",strFileName);
	m_timeoutValue = atoi(strtimeout)*1000;
	m_nDevNum = atoi(strdevnum);
	nscantime = atoi(strscantime);	
	pListCAN = (CListBox*)pWnd->GetDlgItem(IDC_CAN1);
	m_hCANThreadCloseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//	CreateThread(NULL, 0, CanThread, this, 0, NULL);

	if(g_Cfg.cfg_can.b_Only_Recv)
		AfxBeginThread( CanRecvThread, this, THREAD_PRIORITY_HIGHEST );
	else	
		AfxBeginThread( CanThread, this, THREAD_PRIORITY_HIGHEST );
	return TRUE;
}


int Can1::Can_Transfer(CAN_MSG_T cmdMsg,CAN_MSG_T &respMsg)
{
	int ret = 0;
	BOOL bReady = FALSE;
	DWORD		cbReturned = 0;
	ret = CANWriteFile( m_nPort, &bReady, &cmdMsg );
	if(ret)
		return ret;
	if ( !bReady )
	{		
		return -1;
	}
#ifdef _DEBUG
	CString strmsg;								
	strmsg.Format("Send:  %02X%02X%02X%02X%02X%02X%02X%02X",cmdMsg.data[0],cmdMsg.data[1],cmdMsg.data[2],\
		cmdMsg.data[3],cmdMsg.data[4],cmdMsg.data[5],cmdMsg.data[6],cmdMsg.data[7]);
	pListCAN->AddString(strmsg);
#endif
	DWORD t1,t2;
	t1=GetTickCount();
	do 
	{
		ret = CANReadFile(  m_nPort, 1, &respMsg, &cbReturned );
		if(ret)
			return ret;
		if ( !cbReturned )
		{		
			t2 = GetTickCount();
			if( (t2-t1) > m_timeoutValue)
				return -1;
		}
		else
			break;
		
	} while(1);
	
	return 0;
}


UINT  Can1::CanRecvThread(LPVOID lparam)
{
	
	int ret = 0;
	BOOL errflag =FALSE;
	Can1 *pCan1 = (Can1 *)lparam;
	DWORD t1,t2;
	CString strmsg;
	if (CANPortOpen(pCan1->m_nDevNum, (WORD *) &(pCan1->m_nPort), (WORD *) &pCan1->m_nHostID, (WORD *) &pCan1->m_nPreBaudRate) != SUCCESS)
	{
		AddToLog("CAN port open error!\n");
		return FALSE;
	}
	
	if (CANSetProtocolType( pCan1->m_nPort, pCan1->m_wProtocolType ) != SUCCESS)
	{
		AddToLog("CAN SetProtocolType error!\n");
		return FALSE;
	}
	
	
	if (CANHwReset( pCan1->m_nPort ) != SUCCESS)
	{
		AddToLog("CAN port HW Reset error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANInit(pCan1->m_nPort, pCan1->m_nBTR0, pCan1->m_nBTR1, (UCHAR) pCan1->m_nIntMask) != SUCCESS)
	{
		AddToLog("CAN port init error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetOutCtrl(pCan1->m_nPort, pCan1->m_nOutCtrlCode) != SUCCESS)
	{
		AddToLog("CAN set out ctrl code error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetAcp(pCan1->m_nPort, pCan1->m_nAcpCode, pCan1->m_nAcpMask) != SUCCESS)
	{
		AddToLog("CAN set acp code error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetBaud(pCan1->m_nPort, pCan1->m_nBTR0, pCan1->m_nBTR1) != SUCCESS)
	{
		AddToLog("CAN set baud rate error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetNormal(pCan1->m_nPort) != SUCCESS)
	{
		AddToLog("CAN set normal error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	CANEnableEvent( pCan1->m_nPort , TRUE );
	CANEnableRxInt( pCan1->m_nPort );
	pCan1->pListCAN->ResetContent();
	
	BYTE pGetCAN1[8] = {0};
	
	CAN_MSG_T respmsg;
	int nOffset = 0;

	//pGetMSg[7] = CCommon::CRC8_Table(pGetMSg,7);
	
	while (true) 
	{
		
		t1=GetTickCount();		
		
		
		DWORD		cbReturned = 0;
		
		CANReadFile( pCan1->m_nPort, 1, &respmsg, &cbReturned );
		if(!cbReturned)
		{
			t2 = GetTickCount();
			if( (t2-t1) > pCan1->m_timeoutValue)
				break;
			Sleep(TIMEGAP);
			continue;
		}
		t1=GetTickCount();	
		//m_recv_ChkRemote = msg.rtr;
		BYTE pbValue[4] = {0};
		pbValue[0] = respmsg.data[6];
		pbValue[1] = respmsg.data[5];
		pbValue[2] = respmsg.data[4];
		pbValue[3] = respmsg.data[3];
		
		
		
#ifdef _DEBUG
		strmsg.Format("Recv:  %02X%02X%02X%02X%02X%02X%02X%02X  ID : %02X ",respmsg.data[0],respmsg.data[1],respmsg.data[2], \
			respmsg.data[3],respmsg.data[4],respmsg.data[5],respmsg.data[6],respmsg.data[7],respmsg.id);
		pCan1->pListCAN->AddString(strmsg);
		float ftemp;
		memcpy(&ftemp,pbValue,4);
		strmsg.Format("Value %f",ftemp);					
		pCan1->pListCAN->AddString(strmsg);
#endif
		
		if(respmsg.data[7] == CCommon::CRC8_Table(respmsg.data,7))
			errflag = true;
		else
			errflag = false;
		
		if(errflag == false)
			break;
		
		nOffset = respmsg.data[1] - 1;
		//save data
		if(respmsg.id == g_Cfg.cfg_can.b1_id)
		{	
			
			memcpy(&pCan1->cvCAN1[nOffset].fValue,pbValue,4);
			
			pCan1->cvCAN1[nOffset].npos =  g_Cfg.cfg_can.b1_pos[nOffset];
			CString strMin,strMax,strRatio,strPos;
			strPos.Format("%d",pCan1->cvCAN1[nOffset].npos);
			
			strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);
			
			if(strMin.IsEmpty())
				strMin = DEFAULT_MIN;
			if(strMax.IsEmpty())
				strMax = DEFAULT_MAX;
			pCan1->cvCAN1[nOffset].ratio = 1;
			pCan1->cvCAN1[nOffset].Threshold = atof(strMax);
												
		}
		else if(respmsg.id == g_Cfg.cfg_can.b2_id)
		{	
			
			memcpy(&pCan1->cvCAN2[nOffset].fValue,pbValue,4);
			pCan1->cvCAN2[nOffset].npos = g_Cfg.cfg_can.b2_pos[nOffset];
			CString strMin,strMax,strRatio,strPos;
			strPos.Format("%d",pCan1->cvCAN2[nOffset].npos);
			
			strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);
			
			if(strMin.IsEmpty())
				strMin = DEFAULT_MIN;
			if(strMax.IsEmpty())
				strMax = DEFAULT_MAX;
			pCan1->cvCAN2[nOffset].ratio = 1;
			pCan1->cvCAN2[nOffset].Threshold = atof(strMax);
			
			
		}
		else if(respmsg.id == g_Cfg.cfg_can.b3_id)
		{
			
			
			memcpy(&pCan1->cvCAN3[nOffset].fValue,pbValue,4);
			pCan1->cvCAN3[nOffset].npos = g_Cfg.cfg_can.b3_pos[nOffset];
			CString strMin,strMax,strRatio,strPos;
			strPos.Format("%d",pCan1->cvCAN3[nOffset].npos);
			
			strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);
			if(strRatio.IsEmpty())
				strRatio = "1";
			if(strMin.IsEmpty())
				strMin = DEFAULT_MIN;
			if(strMax.IsEmpty())
				strMax = DEFAULT_MAX;
			pCan1->cvCAN3[nOffset].ratio = 1;
			pCan1->cvCAN3[nOffset].Threshold = atof(strMax);
			
			
		}
		else if(respmsg.id == g_Cfg.cfg_can.b4_id)
		{	
			
			memcpy(&pCan1->cvCAN4[nOffset].fValue,pbValue,4);
			pCan1->cvCAN4[nOffset].npos = g_Cfg.cfg_can.b4_pos[nOffset];
			CString strMin,strMax,strRatio,strPos;
			strPos.Format("%d",pCan1->cvCAN4[nOffset].npos);
			
			strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);
			
			if(strMin.IsEmpty())
				strMin = DEFAULT_MIN;
			if(strMax.IsEmpty())
				strMax = DEFAULT_MAX;
			pCan1->cvCAN4[nOffset].ratio = 1;
			pCan1->cvCAN4[nOffset].Threshold = atof(strMax);
			
			
		}
		else
		{
			continue;
		}	
		
		
		
		
		
		if(WaitForSingleObject(pCan1->m_hCANThreadCloseEvent, 50) == WAIT_OBJECT_0)
			break;
		//		break;
	}
	return 1;
}


UINT  Can1::CanThread(LPVOID lparam)
{
	
	int ret = 0;
	BOOL errflag =FALSE;
	Can1 *pCan1 = (Can1 *)lparam;
	DWORD t1,t2;
	CString strmsg;
	if (CANPortOpen(pCan1->m_nDevNum, (WORD *) &(pCan1->m_nPort), (WORD *) &pCan1->m_nHostID, (WORD *) &pCan1->m_nPreBaudRate) != SUCCESS)
	{
		AddToLog("CAN port open error!\n");
		return FALSE;
	}
	
	if (CANSetProtocolType( pCan1->m_nPort, pCan1->m_wProtocolType ) != SUCCESS)
	{
		AddToLog("CAN SetProtocolType error!\n");
		return FALSE;
	}
	
	
	if (CANHwReset( pCan1->m_nPort ) != SUCCESS)
	{
		AddToLog("CAN port HW Reset error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANInit(pCan1->m_nPort, pCan1->m_nBTR0, pCan1->m_nBTR1, (UCHAR) pCan1->m_nIntMask) != SUCCESS)
	{
		AddToLog("CAN port init error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetOutCtrl(pCan1->m_nPort, pCan1->m_nOutCtrlCode) != SUCCESS)
	{
		AddToLog("CAN set out ctrl code error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetAcp(pCan1->m_nPort, pCan1->m_nAcpCode, pCan1->m_nAcpMask) != SUCCESS)
	{
		AddToLog("CAN set acp code error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetBaud(pCan1->m_nPort, pCan1->m_nBTR0, pCan1->m_nBTR1) != SUCCESS)
	{
		AddToLog("CAN set baud rate error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	
	if (CANSetNormal(pCan1->m_nPort) != SUCCESS)
	{
		AddToLog("CAN set normal error!\n");
		CANPortClose(pCan1->m_nPort);
		return FALSE;
	}
	CANEnableEvent( pCan1->m_nPort , TRUE );
	CANEnableRxInt( pCan1->m_nPort );
	pCan1->pListCAN->ResetContent();

	BYTE pGetCAN1[8] = {0};

	

	//pGetMSg[7] = CCommon::CRC8_Table(pGetMSg,7);

	while (true) 
	{
		for(int i = 0; i<4;i++)
		{
			int nOffset = 0;
			int ncount = 0;
			if(i==2 && pCan1->m_bGFFlag == FALSE)
				continue;
			
			int maxtime = atoi(CCommon::GetIniString("CAN","MaxTimes",strFileName));
			
			
			CAN_MSG_T msg;
			CAN_MSG_T respmsg;
			CString s;
			BOOL bReady = FALSE;
			int		nLength;
			DWORD		cbReturned = 0;
			msg.id = atoi(CCommon::GetIniString("CAN","Msg_id",strFileName));
			msg.rtr = 0;
			msg.dlen = 8;
			if(i==0)
				memcpy(pGetCAN1,"\x00\x00\x00\x33\x00\x00\x00\xC0",8);
			else if(i==1)
				memcpy(pGetCAN1,"\x00\x00\x00\x44\x00\x00\x00\xEE",8);
			else if(i==2)
				memcpy(pGetCAN1,"\x00\x00\x00\x55\x00\x00\x00\x59",8);
			else if(i==3)
				memcpy(pGetCAN1,"\x00\x00\x00\x66\x00\x00\x00\x99",8);
			else
				memset(pGetCAN1,0x00,8);
			memcpy(msg.data,pGetCAN1,8);
			
		

//			if(pCan1->Can_Transfer(msg,respmsg)!=SUCCESS)
//				break;
			//clear the
			do
			{
				Sleep(TIMEGAP);
				if(CANReadFile( pCan1->m_nPort, 1, &respmsg, &cbReturned )!=SUCCESS)  // Note:The function can't be used with CANSetBufferPtr()!
					break;
				if(cbReturned)
				{
#ifdef _DEBUG							
				strmsg.Format("Clean Recv:  %02X%02X%02X%02X%02X%02X%02X%02X  ID : %02X ",respmsg.data[0],respmsg.data[1],respmsg.data[2], \
					respmsg.data[3],respmsg.data[4],respmsg.data[5],respmsg.data[6],respmsg.data[7],respmsg.id);
				pCan1->pListCAN->AddString(strmsg);
#endif
				}
			}while (cbReturned);
			
			int errcount = 0;
			do 
			{
				if(CANWriteFile( pCan1->m_nPort, &bReady, &msg )!=SUCCESS)
				{
					errflag = false;
					break;

				}
				else
				{				
					errflag = true;
				}

				errcount++;
				if(errcount > maxtime)
				{
					errflag = false;
					break;
				}
#ifdef _DEBUG	
				if(bReady==0)
				{
					strmsg.Format("WriteFile Error");
					pCan1->pListCAN->AddString(strmsg);
				}
#endif
			} while(!bReady);
		    
			if(errflag == false)
				break;
#ifdef _DEBUG							
	strmsg.Format("Send:  %02X%02X%02X%02X%02X%02X%02X%02X",msg.data[0],msg.data[1],msg.data[2],\
		msg.data[3],msg.data[4],msg.data[5],msg.data[6],msg.data[7]);
	pCan1->pListCAN->AddString(strmsg);
#endif
			t1=GetTickCount();		
			
			

			while(true)
			{
				Sleep(TIMEGAP);

				CANReadFile( pCan1->m_nPort, 1, &respmsg, &cbReturned );
				
				if(!cbReturned)
				{
					t2 = GetTickCount();
					if( (t2-t1) > pCan1->m_timeoutValue)
						break;
					
					Sleep(TIMEGAP);
					continue;
				}
				
				t1=GetTickCount();	
				//m_recv_ChkRemote = msg.rtr;
				BYTE pbValue[4] = {0};
				pbValue[0] = respmsg.data[6];
				pbValue[1] = respmsg.data[5];
				pbValue[2] = respmsg.data[4];
				pbValue[3] = respmsg.data[3];

#ifdef _DEBUG
				strmsg.Format("Recv:  %02X%02X%02X%02X%02X%02X%02X%02X  ID : %02X ",respmsg.data[0],respmsg.data[1],respmsg.data[2], \
					respmsg.data[3],respmsg.data[4],respmsg.data[5],respmsg.data[6],respmsg.data[7],respmsg.id);
				pCan1->pListCAN->AddString(strmsg);
				float ftemp;
				memcpy(&ftemp,pbValue,4);
				strmsg.Format("Value %f",ftemp);					
				pCan1->pListCAN->AddString(strmsg);

				int nCount = pCan1->pListCAN->GetCount();
				if (nCount > 0)
				{
					if(nCount>500)
						pCan1->pListCAN->ResetContent();
					pCan1->pListCAN->SetCurSel(nCount - 1);
				}
#endif
				
				if(respmsg.data[7] == CCommon::CRC8_Table(respmsg.data,7))
					errflag = true;
				else
					errflag = false;
							
				if(errflag == false)
					break;
							
				//save data
				nOffset = respmsg.data[1] - 1;
				if(i==0)
				{	
					if(respmsg.data[0] != CAN1_channelNum )
						break;
					
					memcpy(&pCan1->cvCAN1[nOffset].fValue,pbValue,4);
					
					pCan1->cvCAN1[nOffset].npos =  g_Cfg.cfg_can.b1_pos[nOffset];
					CString strMin,strMax,strRatio,strPos;
					strPos.Format("%d",pCan1->cvCAN1[nOffset].npos);
					
					strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);

					if(strMin.IsEmpty())
						strMin = DEFAULT_MIN;
					if(strMax.IsEmpty())
						strMax = DEFAULT_MAX;
					pCan1->cvCAN1[nOffset].ratio = 1;
					pCan1->cvCAN1[nOffset].Threshold = atof(strMax);
					
					pCan1->IsOverPress(pCan1->cvCAN1[nOffset].npos,pCan1->cvCAN1[nOffset].fValue);
					ncount++;
					if(ncount == CAN1_channelNum )
						break;
					
					
				}
				else if(i==1)
				{	
					if(respmsg.data[0] != CAN2_channelNum )
						break;
					
					memcpy(&pCan1->cvCAN2[nOffset].fValue,pbValue,4);
					pCan1->cvCAN2[nOffset].npos = g_Cfg.cfg_can.b2_pos[nOffset];
					CString strMin,strMax,strRatio,strPos;
					strPos.Format("%d",pCan1->cvCAN2[nOffset].npos);
					
					strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);
					
					if(strMin.IsEmpty())
						strMin = DEFAULT_MIN;
					if(strMax.IsEmpty())
						strMax = DEFAULT_MAX;
					pCan1->cvCAN2[nOffset].ratio = 1;
					pCan1->cvCAN2[nOffset].Threshold = atof(strMax);
					pCan1->IsOverPress(pCan1->cvCAN2[nOffset].npos,pCan1->cvCAN2[nOffset].fValue);
					ncount++;
					if(ncount == CAN2_channelNum )
						break;

					
				}
				else if(i==2)
				{
					
					if(respmsg.data[0] != CAN3_channelNum )
						break;
					
					memcpy(&pCan1->cvCAN3[nOffset].fValue,pbValue,4);
					pCan1->cvCAN3[nOffset].npos = g_Cfg.cfg_can.b3_pos[nOffset];
					CString strMin,strMax,strRatio,strPos;
					strPos.Format("%d",pCan1->cvCAN3[nOffset].npos);

					strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);
					if(strRatio.IsEmpty())
						strRatio = "1";
					if(strMin.IsEmpty())
						strMin = DEFAULT_MIN;
					if(strMax.IsEmpty())
						strMax = DEFAULT_MAX;
					pCan1->cvCAN3[nOffset].ratio = 1;
					pCan1->cvCAN3[nOffset].Threshold = atof(strMax);
					pCan1->IsOverPress(pCan1->cvCAN3[nOffset].npos,pCan1->cvCAN3[nOffset].fValue);
					ncount++;
					if(ncount == CAN3_channelNum )
					{
						pCan1->m_bGFFlag = FALSE;
						break;
					}
					
				}
				else if(i==3)
				{	
					if(respmsg.data[0] != CAN4_channelNum )
						break;
					
					memcpy(&pCan1->cvCAN4[nOffset].fValue,pbValue,4);
					pCan1->cvCAN4[nOffset].npos = g_Cfg.cfg_can.b4_pos[nOffset];
					CString strMin,strMax,strRatio,strPos;
					strPos.Format("%d",pCan1->cvCAN4[nOffset].npos);

					strMax = CCommon::GetIniString(strPos,"Threshold",strFileName);
	
					if(strMin.IsEmpty())
						strMin = DEFAULT_MIN;
					if(strMax.IsEmpty())
						strMax = DEFAULT_MAX;
					pCan1->cvCAN4[nOffset].ratio = 1;
					pCan1->cvCAN4[nOffset].Threshold = atof(strMax);
					pCan1->IsOverPress(pCan1->cvCAN4[nOffset].npos,pCan1->cvCAN4[nOffset].fValue);
					ncount++;
					if(ncount == CAN4_channelNum )
						break;									
					
				}
				else
				{
					break;
				}	
				
			}
				
		}
			
			
			
			if(WaitForSingleObject(pCan1->m_hCANThreadCloseEvent, 50) == WAIT_OBJECT_0)
				break;
			Sleep(pCan1->nscantime);
			//		break;
	}
	return 1;
}

void Can1::SetGFFlag()
{
	m_bGFFlag = TRUE;
}

void Can1::StopThread()
{
	SetEvent(m_hCANThreadCloseEvent);
}


void Can1::GetCAN1Value(ChannelValue Buf[CAN1_channelNum])
{	
	for(int i=0;i<CAN1_channelNum;i++)
		Buf[i] = cvCAN1[i];
}
	
void Can1::GetCAN2Value(ChannelValue Buf[CAN2_channelNum])
{
	for(int i=0;i<CAN2_channelNum;i++)
		Buf[i] = cvCAN2[i];
}

void Can1::GetCAN3Value(ChannelValue Buf[CAN3_channelNum])
{
	for(int i=0;i<CAN3_channelNum;i++)
		Buf[i] = cvCAN3[i];

}

void Can1::GetCAN4Value(ChannelValue Buf[CAN4_channelNum])
{
	for(int i=0;i<CAN4_channelNum;i++)
		Buf[i] = cvCAN4[i];
}

void Can1::IsOverPress(int npos,float fvalue)
{
	
	if(g_Cfg.cfg_system.bAutoSetDo)
	{
		CString strPos;
		CString strThresholdValue;
		CString strDOPos;
		CString strEventId;
		CString strEventNo;
		strPos.Format("%d",npos);
		strThresholdValue = CCommon::GetIniString(strPos,"Threshold",strFileName);
		strDOPos = CCommon::GetIniString(strPos,"DO",strFileName);
		strEventId = CCommon::GetIniString(strPos,"EventId",strFileName);
		strEventNo = CCommon::GetIniString(strPos,"EventNo",strFileName);
		if(fvalue  > atof(strThresholdValue))
		{
			if(atoi(strDOPos) > 0 && atoi(strDOPos)<25 )
			{
				g_Dio.SetDoBit(atoi(strDOPos),CCommon::getDoBit(atoi(strDOPos),0));				
			}
			if(!strEventId.IsEmpty() && !strEventNo.IsEmpty())
			{
				g_Tcp.SendEvent(atoi(strEventId),atoi(strEventNo));
			}
		}						
	}
}